/*
 * @Author: silence
 * @Date: 2022-02-07 16:36:06
 * @LastEditors: Please set LastEditors
 * @LastEditTime: 2023-10-30 09:23:46
 * @Description: 文件头部注释
 * @FilePath: /lib/utils/api/ApiUtils.dart
 */

import 'dart:convert';

// import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:ems_neutral_app/pages/Mine/Language/SilLocalizations/SilLocalizations.dart';
import 'package:flutter/material.dart';
import 'package:sil_base_widget_package/sil_base_widget_package.dart';
import '../../../api/NetCacheInterceptor.dart';
import '../../../api/NetParamInterceptor.dart';
import '../../../api/R.dart';
import '../../../config/AppInfo.dart';
import '../../../utils/color/ColorUtils.dart';

import 'package:sil_utils_package/sil_utils_package.dart';

import '../main.dart';
import 'NetApiInterceptor.dart';
import 'dart:io';

class ApiUtils {
  static String GetMethod = 'get';
  static String PostMethd = 'post';
  static String PutMethd = 'put';
  static String DeleteMethd = 'delete';

  /**
   * @description: 初始化dio
   * @param {*}
   * @return {*}
   */
  static Dio initDio(
      {Map<String, dynamic>? headers,
      Map<String, dynamic>? extra,
      bool isUseBaseUrl = true,
      bool isFormData = false}) {
    BaseOptions baseOptions = SilTools.mapIsEmpty(headers)
        ? BaseOptions(
            connectTimeout: Duration(milliseconds: RequestTimeout),
            receiveTimeout: Duration(milliseconds: RequestTimeout),
            extra: extra)
        : BaseOptions(
            headers: headers,
            connectTimeout: Duration(milliseconds: RequestTimeout),
            receiveTimeout: Duration(milliseconds: RequestTimeout),
            extra: extra);

    // 是否使用host
    if (isUseBaseUrl) {
      baseOptions.baseUrl = BaseUrl;
    }
    Dio dio = Dio(baseOptions);

    // 添加缓存拦截器
    dio.interceptors.add(NetCacheInterceptor());
    // 添加公共参数处理拦截器
    dio.interceptors.add(NetParamInterceptor(
        isNeedHandler: isUseBaseUrl, isFormData: isFormData));
    // 添加接口处理拦截器
    dio.interceptors.add(NetApiInterceptor(isNeedHandler: isUseBaseUrl));

    // 解决证书验证问题，验证强制返回true：
    dio.httpClientAdapter = IOHttpClientAdapter(
      createHttpClient: () {
        final client = HttpClient();

        // 设置代理
        if (PROXY_PATH.isNotEmpty) {
          client.findProxy = (url) => PROXY_PATH;
        }
        return client;
      },
    );
    return dio;
  }

  static Dio initDownImgDio() {
    BaseOptions baseOptions = BaseOptions(
        connectTimeout: Duration(milliseconds: RequestTimeout),
        receiveTimeout: Duration(milliseconds: RequestTimeout),
        responseType: ResponseType.bytes);

    Dio dio = Dio(baseOptions);
    // 解决证书验证问题，验证强制返回true：
    (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
        (client) {
      client.badCertificateCallback = (cert, host, port) {
        return true;
      };
      return null;
    };
    return dio;
  }

  /**
   * @description: 发送网络请求
   * @param method 请求方式; path 请求的地址; param 请求参数; isFormData 是否表单数据; headers 请求头; isUseBaseUrl 是否使用host;showErrorToast 是否显示网络错误提示
   *        noFormatData 非正常格式返回
   * @return {*}
   */
  static Future<Map<String, dynamic>> methodAwait(String method, String url,
      {Map<String, dynamic>? param,
      Map<String, dynamic>? extra,
      bool isFormData = false,
      Map<String, dynamic>? headers,
      bool isUseBaseUrl = true,
      bool isShowLog = true,
      bool showErrorToast = true,
      bool isUploadFile = false,
      bool noFormatData = false}) async {
    late Dio dio;
    late Map<String, dynamic> result;

    if (param == null) param = Map(); // 处理参数为空的情况

    try {
      var response = null;
      dio = initDio(
          headers: headers,
          isUseBaseUrl: isUseBaseUrl,
          extra: extra,
          isFormData: isFormData);

      if (method == GetMethod) {
        response = await dio.get(url, queryParameters: param);
      } else if (method == PostMethd) {
        dynamic tempParam = param;
        response = await dio.post(url, data: tempParam);
      } else if (method == PutMethd) {
        dynamic tempParam = param;
        response = await dio.put(url, data: tempParam);
      } else if (method == DeleteMethd) {
        dynamic tempParam = param;
        response = await dio.delete(url, data: tempParam);
      }

      var data = response.data;

      /// 上传文件，返回的只有一条地址的情况
      if (isUploadFile) {
        result = {'code': 0, 'data': data};
      } else {
        /// 非正常格式，不做处理，直接返回数据
        if (noFormatData) {
          result = {'code': 0, 'data': data};
        } else {
          /// 普通请求解决处理
          if (data is String) {
            result = json.decode(data);
          } else {
            result = data as Map<String, dynamic>;
          }
        }
      }
    } catch (e) {
      result = {'error': e};
      String? prompt =
          LangOf(navigatorKey.currentState!.context)?.netErr?.net_err;
      if (showErrorToast) SilToast.show(prompt ?? '网络不给力，请稍后重试');
    } finally {
      // 打印请求的信息
      if (isShowLog)
        SilLog.p(
            url: (dio.options.baseUrl + url),
            param: {'headers': dio.options.headers, 'body': param},
            result: result);

      return result;
    }
  }
}

/**
 * @description: 接口处理：非列表接口使用
 * @param {
 *  api：接口处理函数
 *  success：成功回调函数
 *  failure：失败回调函数
 *  promptText：自定义loading提示
 *  showLoading: 是否loading
 *  showErrorToast：是否显示错误提示
 *  elseSuccessCode:其他返回的正确的code码
 * }
 * @return {*}
 */
Future apiShow(BuildContext context,
    {required Future api,
    required Function(dynamic) success,
    Function(dynamic)? failure,
    String? promptText,
    bool showLoading = false,
    bool showErrorToast = true,
    int? elseSuccessCode}) async {
  // loading
  if (showLoading) {
    String promptTextStr = LangOf(context)?.common?.loading ?? "加载中...";
    SilAlertDialog.showLoadingDialog(context,
        indicatorColor: ColorUtils.color_theme,
        promptText: promptText ?? promptTextStr,
        promptTextStyle:
            TextStyle(color: ColorUtils.color_theme, fontSize: 14.sp));
  }

  R result = R();
  String prompt = LangOf(navigatorKey.currentState!.context)?.netErr?.net_err ??
      '网络不给力，请稍后重试';
  try {
    result = await api;
  } catch (e) {
    result.error = Future.error(e);
    result.message = prompt;
  } finally {
    //将loading弹窗消失掉
    if (showLoading) Navigator.pop(context);

    // 网络异常
    if (result.error != null) {
      if (failure != null) failure(result);
    } else {
      // 接口正常返回
      if (result.code != null &&
          (result.code == 0 ||
              result.code == 200 ||
              result.code == elseSuccessCode)) {
        // 数据获取成功
        success(result);
      } else {
        // 数据获取失败
        if (failure != null) {
          failure(result);
        } else {
          if (showErrorToast) SilToast.show(result.message ?? prompt);
        }
      }
    }
  }
}
